package com.paipaideli.common.http;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.paipaideli.ApiService;
import com.paipaideli.BuildConfig;
import com.paipaideli.MyApplication;
import com.paipaideli.common.base.BaseResponse;
import com.paipaideli.common.utils.ConnecStatusUtils;
import com.paipaideli.common.utils.ToastUtil;
import com.paipaideli.common.utils.preferrnces.FastData;
import com.paipaideli.ui.login.LoginActivity;

import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.CacheControl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class Api {

    public static Api api = null;
    private static final String PLATFORM = "android";
    private static final String CLIENT = "paipaideli";

    public static ApiService getInstanceGson() {

        if (api == null) {
            api = new Api();
        }
        return api.getService();
    }

    private ApiService getService() {
        return apiService();
    }

    private ApiService apiService() {
        Retrofit.Builder retrofitBuilder = new Retrofit.Builder();

        Retrofit retrofit = retrofitBuilder
                .baseUrl(BuildConfig.BASE_URL + "/")
                .client(client().build())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(ApiService.class);
    }

    private static OkHttpClient.Builder client() {
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
        httpClientBuilder.writeTimeout(30, TimeUnit.SECONDS);
        httpClientBuilder.readTimeout(30, TimeUnit.SECONDS);
        addCheckNetworkChain(httpClientBuilder);
        httpClientBuilder.networkInterceptors()
                .add(chain -> {
                    Request.Builder req = chain.request().newBuilder();
                    req.addHeader("Accept-Charset", "utf-8");
                    req.addHeader("Content-Type", "application/json")
                            .addHeader("Connection", "keep-alive")
                            .addHeader("Accept", "*/*")
                            .addHeader("x-version", BuildConfig.VERSION_NAME)
                            .addHeader("x-platform", PLATFORM)
                            .addHeader("x-client", CLIENT)
                            .addHeader("DeviceNumber", ConnecStatusUtils.getAndroidId(MyApplication.getInstanse()));
                    addAuthorizationHeader(req);
                    Response response = chain.proceed(req.build());
                    return response.newBuilder().build();
                });
        httpClientBuilder.addInterceptor(
                new HttpLoggingInterceptor().setLevel(
                        HttpLoggingInterceptor.Level.BODY
                )
        );

        httpClientBuilder.addNetworkInterceptor(chain -> {
            /*
             * 接口字段返回 拦截器
             * */
            Charset UTF8 = Charset.forName("UTF-8");

            Response response = chain.proceed(chain.request());
            ResponseBody responseBody = response.body();
            Log.d("response", response.toString());
            String resultsBody = null;
            if (HttpHeaders.hasBody(response)) {
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE); // Buffer the entire body.
                Buffer buffer = source.buffer();
                Charset charset = UTF8;
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    try {
                        charset = contentType.charset(UTF8);
                    } catch (UnsupportedCharsetException e) {
                        e.printStackTrace();
                    }
                }
                resultsBody = buffer.clone().readString(charset);

            }
            String date = response.headers().newBuilder().get("Date");
            if(!TextUtils.isEmpty(date)){
                FastData.setTime(date);
            }else{
                FastData.setTime("");
            }
            Log.e("date",date);
            try {
                if (resultsBody != null && !TextUtils.isEmpty(resultsBody) && response.code() == 200) {
                    Gson gson = new Gson();
                    BaseResponse baseResponse = gson.fromJson(resultsBody, BaseResponse.class);
                    Log.e("tag", baseResponse.getCode());
                    if (baseResponse.getCode().equals("401")) {
                        FastData.setToken("");
                        LoginActivity.open(MyApplication.getInstance());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return response;
        });
        return httpClientBuilder;
    }

    private static void addCheckNetworkChain(OkHttpClient.Builder httpClientBuilder) {
        httpClientBuilder.addInterceptor(chain -> {
            Request request = chain.request();
            if (!ConnecStatusUtils.isNetworkAvailable()) {
                Maybe.just("没有可用网络, 请连接网络后重试")
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(ToastUtil::show, throwable -> {
                            Log.e("Debug", "error", throwable);
                        });
                // @notice  由于服务器不支持缓存，所以这里其实是没有起作用，等服务器起作用就可以了
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }
            return chain.proceed(request)
                    .newBuilder()
                    .build();
        });
    }

    private static void addAuthorizationHeader(Request.Builder req) {
        if (!TextUtils.isEmpty(FastData.getToken())) {
            req.addHeader("Authorization", FastData.getToken());
        } else {
            req.addHeader("Authorization", "Basic bGc6YmFyQExn");
        }
    }

}
